package com.pozu.new_retail.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.pozu.new_retail.dao.model.AppSetting;
import com.pozu.new_retail.dao.model.Code;
import com.pozu.new_retail.dao.model.Goods;
import com.pozu.new_retail.dao.model.GoodsExt;
import com.pozu.new_retail.dao.model.ShoppingCart;
import com.pozu.new_retail.dao.model.User;
import com.pozu.new_retail.dao.pay.wx.WXCallBackInfo;
import com.pozu.new_retail.dao.pay.wx.WXCallBackReturn;
import com.pozu.new_retail.dao.pay.wx.WXPrePayOrder;
import com.pozu.new_retail.dao.pay.wx.WXPrePayReturns;
import com.pozu.new_retail.dao.pay.wx.WXQueryOrder;
import com.pozu.new_retail.dao.pay.wx.WXQueryOrderReturn;
import com.pozu.new_retail.dao.vo.OrderVo;
import com.pozu.new_retail.dao.vo.ShoppingCartVo;
import com.pozu.new_retail.utils.CodeConstants;
import com.pozu.new_retail.utils.LogUtils;
import com.pozu.new_retail.utils.PayTools;
import com.pozu.new_retail.utils.Tools;
import com.pozu.new_retail.dao.mapper.AppSettingMapper;
import com.pozu.new_retail.dao.mapper.GoodsExtMapper;
import com.pozu.new_retail.dao.mapper.GoodsMapper;
import com.pozu.new_retail.dao.mapper.OrderMapper;
import com.pozu.new_retail.dao.mapper.ScoresRecordMapper;
import com.pozu.new_retail.dao.mapper.ShoppingCartMapper;
import com.pozu.new_retail.dao.mapper.UserMapper;
import com.pozu.new_retail.dao.model.Order;
import com.pozu.new_retail.dao.model.ScoresRecord;
import com.pozu.new_retail.service.CodeService;
import com.pozu.new_retail.service.OrderService;

@Service("orderService")
public class OrderServiceImpl implements OrderService {

	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private ShoppingCartMapper shoppingCartMapper;
	@Autowired
	private AppSettingMapper appSettingMapper;
	@Autowired
	private GoodsExtMapper goodsExtMapper;
	@Autowired
	private GoodsMapper goodsMapper;
	@Autowired
	private ScoresRecordMapper scoresRecordMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private CodeService codeService;
	
	@Override
	public Order queryByOrderId(String orderId) {
		return orderMapper.queryByOrderId(orderId);
	}

	@Override
	public int updateOrder(Order order) {
		order.setUpdatedTime(System.currentTimeMillis());
		return orderMapper.updateOrder(order);
	}

//	@Override
//	public String queryCodeByUserId(long userId) {
//		return orderMapper.queryCodeByUserId(userId);
//	}

	@Override
	public int queryOrderCountByMap(HashMap<String, Object> map) {
		return orderMapper.queryOrderCountByMap(map);
	}
	
	@Override
	public Order queryByPrepayId(String prepayId) {

		return orderMapper.queryByPrepayId(prepayId);
	}
	
	@Override
	public WXPrePayReturns wxAddOrder(Order order,String wx_AppId,String wx_MchId,String wx_MchKey) throws Exception {
		
		long userId = order.getUserId();
		
		String out_trade_no = order.getOrderId();
		
		double money = order.getMoney();

		String wx_notify_url = PayTools.wx_notify_url;//接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数
		String trade_type = PayTools.wx_trade_type;//支付类型
		String wx_pay_url = PayTools.wx_pay_url;//微信下单地址
		String body = "奇货本色";
		String nonce_str = PayTools.generateRandCode();//随机字符串
		
		String attach = userId+"";//附加数据
		
		//向微信发起请求
		WXPrePayOrder ppo = new WXPrePayOrder();
		ppo.setAppid(wx_AppId);
		ppo.setMch_id(wx_MchId);
		ppo.setNotify_url(wx_notify_url);
		ppo.setTrade_type(trade_type);
		ppo.setBody(body);
		ppo.setNonce_str(nonce_str);
		ppo.setOut_trade_no(out_trade_no);
		ppo.setTotal_fee((int)(Tools.getDoubleValue(money*100)));
		ppo.setAttach(attach);
		ppo.setSpbill_create_ip(order.getSpbill_create_ip());
		ppo.setOpenid(order.getOpenId());
		ppo.setSign(PayTools.createWXPrePaySign(ppo,wx_MchKey));
		
		String xmlString = PayTools.convertToXml(ppo);
		String returnString  = PayTools.httpPost(wx_pay_url, xmlString);
		
		WXPrePayReturns ppr = (WXPrePayReturns) PayTools.convertXmlStrToObject(WXPrePayReturns.class, returnString);
		ppr.setOrderId(out_trade_no);
		return ppr;
	}

	@Override
	public int queryWXOrder(Order order,String wx_AppId,String wx_MchId,String wx_MchKey) throws Exception {
		
		String nonce_str = PayTools.generateRandCode();//随机字符串
		
		WXQueryOrder wxo = new WXQueryOrder();
		wxo.setAppid(wx_AppId);
		wxo.setMch_id(wx_MchId);
		wxo.setOut_trade_no(order.getOrderId());
		wxo.setNonce_str(nonce_str);
		wxo.setSign(PayTools.createWXQueryOrderSign(wxo,wx_MchKey));
		String wx_order_query_url = PayTools.wx_order_query_url;//微信订单查询地址
		String xmlString = PayTools.convertToXml(wxo);
		String returnString  = PayTools.httpPost(wx_order_query_url, xmlString);
		WXQueryOrderReturn qor = (WXQueryOrderReturn) PayTools.convertXmlStrToObject(WXQueryOrderReturn.class, returnString);
		if(qor.getReturn_code().equals("FAIL")){
			LogUtils.ERROR.error("失败原因,{}",qor.getReturn_msg());
			return CodeConstants.ORDERERROR_MSG;
		}
		
		if(qor.getResult_code().equals("FAIL")){
			LogUtils.ERROR.error("查询微信支付业务错误");
			return CodeConstants.ORDERERROR_MSG;
		}
		
		if(qor.getTrade_state().equals("SUCCESS")){
			
			if(qor.getCash_fee() <= Tools.getDoubleValue(order.getMoney()*100 - 10)){
				LogUtils.INFO.info("用户:{},查询订单:{}出错,实付金额:{},应付金额:{}",order.getUserId(),order.getOrderId(),qor.getCash_fee(),order.getMoney()*100);
				return CodeConstants.ORDERERROR_MSG;
			}
			
			//支付成功 更新订单信息
			Order temp = new Order();
			temp.setOrderId(order.getOrderId());
			
			if (order.getOrderType() == 3) {
				temp.setOrderState(3);
			}else {
				temp.setOrderState(1);
			}
			
			temp.setPrepayId(qor.getTransaction_id());
			temp.setUpdatedTime(System.currentTimeMillis());
			updateOrder(temp);
			handlePayedOrder(order);
			return CodeConstants.SUCCESS_CODE;
		}else if(qor.getTrade_state().equals("NOTPAY")){
			//订单未支付
			return CodeConstants.ORDERUNPAY_MSG;
		}else if(qor.getTrade_state().equals("CLOSED")){
			//订单已经关闭
			return CodeConstants.ORDERCLOSED_MSG;
		}else if(qor.getTrade_state().equals("USERPAYING")){
			//用户支付中
			return CodeConstants.ORDERPAYING_MSG;
		}else if(qor.getTrade_state().equals("PAYERROR")){
			//支付失败(其他原因,如银行返回失败)
			return CodeConstants.ORDERERROR_MSG;
		}
		return CodeConstants.ORDERERROR_MSG;
	}

	@Override
	public String wxCallBack(String callBackString) throws Exception {
		
		WXCallBackInfo cbi = (WXCallBackInfo) PayTools.convertXmlStrToObject(WXCallBackInfo.class, callBackString);
		
		String out_trade_no = cbi.getOut_trade_no();//商户订单号
		Order info = queryByOrderId(out_trade_no);
		
		if(null == info){
			return null;
		}
		
		int appId = info.getAppId();
		
		if(appId <=0 ){
			return null;
		}
		
		AppSetting appSetting = appSettingMapper.queryByAppId(appId);
		
		WXCallBackReturn cbr = new WXCallBackReturn();
		
		if(cbi.getResult_code().equals("SUCCESS")){
		
			if(!PayTools.createWXCallBackInfoSign(cbi,appSetting.getMchKey()).equals(cbi.getSign())){
				//签名不正确
				cbr.setReturn_code("FAIL");
				cbr.setReturn_msg("签名失败");
			}else{
				double price = cbi.getTotal_fee();//验证金额
				String userId = cbi.getAttach().split(",")[0];
				String wx_AppId = appSetting.getWxAppId();//appid
				String wxOrderId = cbi.getTransaction_id();
				
				//1appid2订单号3用户id4订单金额
				if(!wx_AppId.equals(cbi.getAppid())||null==info||
						info.getUserId() != Long.parseLong(userId)||info.getMoney()*100!=price){
					cbr.setReturn_code("FAIL");
					cbr.setReturn_msg("参数格式校验错误");
				}else{
					if(info.getOrderState()==0){
						Order newInfo = new Order();
						newInfo.setOrderId(out_trade_no);
						newInfo.setPrepayId(wxOrderId);
						newInfo.setUpdatedTime(System.currentTimeMillis());
						
						if (info.getOrderType() == 3) {
							newInfo.setOrderState(3);
						}else {
							newInfo.setOrderState(1);
						}
						
						updateOrder(newInfo);
						handlePayedOrder(info);
					}
					cbr.setReturn_code("SUCCESS");
					cbr.setReturn_msg("OK");
				}	
			}
		}else{
			return null;
		}
		return PayTools.convertToXml(cbr);
	}

	@Override
	public void handlePayedOrder(Order order) {
		
		if (order.getOrderType() == 3) {
			String orderId = "wxorder"+Tools.getDateStr("yyyyMMddHHmmssSSS")+Tools.getRandomNumber(6);//订单号
			//预付订金支付完成
			Order secOrder = new Order();
			secOrder.setOrderId(orderId);
			secOrder.setAppId(order.getAppId());
			secOrder.setChannelId(order.getChannelId());
			secOrder.setUserId(order.getUserId());
			secOrder.setNumber(1);
			secOrder.setReceiver(order.getReceiver());
			secOrder.setPhone(order.getPhone());
			secOrder.setAddress(order.getAddress());
			secOrder.setOrderType(2);
			secOrder.setPreStartTime(order.getPreStartTime());
			secOrder.setPreMinNumber(order.getPreMinNumber());
			secOrder.setPrePayLimitDays(order.getPrePayLimitDays());
			long time = System.currentTimeMillis();
			
			secOrder.setCreatedTime(time);
			secOrder.setUpdatedTime(time);
			
			ShoppingCart cart = shoppingCartMapper.queryByOrderId(order.getOrderId()).get(0);
			
			int goodsExtId = cart.getGoodsExtId();
			
			GoodsExt ext = goodsExtMapper.queryByGoodsExtId(goodsExtId);
			
			int goodsId = ext.getGoodsId();
			
			Goods goods = goodsMapper.queryInfoByGoodsId(goodsId);
			
			AppSetting appSetting = appSettingMapper.queryByAppId(order.getAppId());
			
			double expressMoney = appSetting.getExpressMoney();//快递费金额
			
			secOrder.setPreDeposit(goods.getPreDepoist());
			secOrder.setExpressMoney(expressMoney);
			secOrder.setMoney(ext.getPrice() - goods.getPreDepoist() + expressMoney);
			
			orderMapper.insertOrder(secOrder);

			ShoppingCart temp = new ShoppingCart();
			temp.setSecOrderId(orderId);
			temp.setShoppingCartId(cart.getShoppingCartId());
			temp.setUpdatedTime(System.currentTimeMillis());
			shoppingCartMapper.updateShoppingCart(temp);
		}else {
//			//支付成功后批量减库存
//			List<ShoppingCart> carts = shoppingCartMapper.queryByOrderId(order.getOrderId());
//			
//			List<GoodsExt> goodsExts = new ArrayList<GoodsExt>();
//			
//			for(ShoppingCart cart:carts) {
//				GoodsExt ext = new GoodsExt();
//				ext.setGoodsExtId(cart.getGoodsExtId());
//				ext.setNumber(cart.getNumber());
//				ext.setUpdatedTime(System.currentTimeMillis());
//				goodsExts.add(ext);
//			}
//			
//			goodsExtMapper.batchUpdate(goodsExts);	
			//处理组团码（渠道码、母码与超级码、微代理码还有普通码不是同一个）
			String usingCode = order.getCode();//使用的组团码
			Integer usingCodeLevel = order.getLevel();//组图码等级
			//使用了组团码
			if (!StringUtils.isEmpty(usingCode)) {
				Long userId = order.getUserId();//用户id
				Integer appId = order.getAppId();//订单所属小程序id
				
				Code selfCodeObj = codeService.queryCodeObjByUserId(appId, userId);
	
				//并且自己本身存在且是普通组团码
				if (null != selfCodeObj && selfCodeObj.getLevel() == 0) {
					if (usingCodeLevel == 4 || usingCodeLevel == 2) {
						//使用的组团码为母码或者是KOL
						Code newCode = new Code();
						newCode.setId(selfCodeObj.getId());
						newCode.setReferCode(usingCode);
						codeService.updateCode(newCode);
					}else if (usingCodeLevel == 0 && appId == 10006) {
						
						HashMap<String, Object> map = new HashMap<String, Object>();

						map.put("code", usingCode);
						map.put("level", 0);
						
						Code usingCodeObj = codeService.queryCodeByMap(map);
						
						//如果上级码存在且为母码则自己也成为子码
						String referCode = usingCodeObj.getReferCode();
						if(!StringUtils.isEmpty(referCode)) {
							
							map.put("code", referCode);
							map.put("appId", appId);
							map.put("level", 4);
							
							Code referCodeObj = codeService.queryCodeByMap(map);
							if (null != referCodeObj) {
								Code newCode = new Code();
								newCode.setId(selfCodeObj.getId());
								newCode.setReferCode(referCode);
								codeService.updateCode(newCode);
							}
						}
					}
					
					
					HashMap<String, Object> map = new HashMap<String, Object>();

					map.put("code", usingCode);
					map.put("level", 4);
					
					Code usingCodeObj = codeService.queryCodeByMap(map);
					if (null != usingCodeObj) {
						
					}	
				}
			}
			
		}
		
		User user = userMapper.queryByUserId(order.getUserId());
		
		User temp = new User();
		temp.setUserId(order.getUserId());
		temp.setScores(user.getScores()+(int)(order.getMoney()/100));

		temp.setUpdatedTime(System.currentTimeMillis());
		userMapper.updateUser(temp);
		
		//产生积分
		ScoresRecord scoresRecord = new ScoresRecord();
		scoresRecord.setUserId(order.getUserId());
		scoresRecord.setScores((int)(order.getMoney()/100));
		scoresRecord.setType(0);
		scoresRecord.setCreatedTime(System.currentTimeMillis());
		scoresRecordMapper.insertScoresRecord(scoresRecord);
	}

	@Override
	public Order saveOrder(List<ShoppingCart> carts, long userId,String receiver,String phone,String address,int appId,int channelId,String code,Integer level,Integer codeDiscount,double expressMoney,double scores) {
		
		String out_trade_no = "wxorder"+Tools.getDateStr("yyyyMMddHHmmssSSS")+Tools.getRandomNumber(6);//订单号
		
		double money = 0;
		
		int totalNumber = 0;
		
		Order order = new Order();
		
		int discount = 0;
		double discountMoney = 0;
		
		for(ShoppingCart cart:carts) {
			if (null != cart) {
				
				int goodsExtId = cart.getGoodsExtId();
				
				GoodsExt ext = goodsExtMapper.queryByGoodsExtId(goodsExtId);
				
				Goods goods = goodsMapper.queryInfoByGoodsId(ext.getGoodsId());

				cart.setUpdatedTime(System.currentTimeMillis());
				cart.setOrderId(out_trade_no);
				cart.setState(1);
				totalNumber += cart.getNumber();
				
				if (goods.getSaleType() == 0) {
					//预售商品支付订金
					order.setGoodsMoney(ext.getPrice());
					order.setMoney(goods.getPreDepoist());
					order.setPreStartTime(goods.getPreStartTime());
					order.setPreMinNumber(goods.getPreMinNumber());
					order.setPrePayLimitDays(goods.getPrePayLimitDays());
					order.setOrderType(3);
				}else{
					double cartMoney = cart.getNumber() * ext.getPrice();
					if (cart.getDiscount() > 0) {
						//分享来的
						discount = cart.getDiscount();
						
						discountMoney += cartMoney*discount/100;
						
						order.setOrderType(1);
					} 
					money += cartMoney;
				}

			}
		}
		
		if (null == order.getOrderType()) {
			order.setOrderType(0);
		}
		
		shoppingCartMapper.batchUpdate(carts);
		
		if (order.getOrderType() != 3) {
			order.setGoodsMoney(money);
		}
		order.setDiscount(discount);
		order.setDiscountMoney(discountMoney);
		order.setLevel(level);
	
		if (null != code && null != codeDiscount) {
			//组团码优惠
			
			double codeMoney = money*codeDiscount/100;
			
			money -= codeMoney;
			order.setCodeMoney(codeMoney);
		}
		
		if (discountMoney > 0) {
			money -= discountMoney;
		}
		
		order.setScores(scores);
		
		if (scores > 0) {
			//消耗积分
			money -= scores;
			
			User user = userMapper.queryByUserId(userId);
			
			User temp = new User();
			temp.setUserId(userId);
			temp.setScores(user.getScores()-scores);
			if (temp.getScores() < 0) {
				temp.setScores(0d);
			}
			temp.setUpdatedTime(System.currentTimeMillis());
			userMapper.updateUser(temp);
			
			ScoresRecord scoresRecord = new ScoresRecord();
			scoresRecord.setUserId(userId);
			scoresRecord.setScores(-scores);
			scoresRecord.setType(1);
			scoresRecord.setCreatedTime(System.currentTimeMillis());
			scoresRecordMapper.insertScoresRecord(scoresRecord);
			
		}
		
		//加邮费
		if (order.getOrderType() != 3) {
			money+=expressMoney;
			order.setExpressMoney(expressMoney);
		}
		
		if(money < 0){
			money = 0;
		}
		
		order.setOrderId(out_trade_no);
		order.setUserId(userId);
		order.setNumber(totalNumber);
		order.setCode(code);
		
		if (order.getOrderType() != 3) {
			order.setMoney(money);
		}
		
		order.setReceiver(receiver);
		order.setPhone(phone);
		order.setAddress(address);
		order.setAppId(appId);
		order.setChannelId(channelId);
		
		long time = System.currentTimeMillis();
		
		order.setCreatedTime(time);
		order.setUpdatedTime(time);
		//入库操作
		orderMapper.insertOrder(order);
		return order;
	}

	@Override
	public List<OrderVo> queryOrderList(Map<String, Object> map) {
		List<OrderVo> vos = new ArrayList<OrderVo>();
		List<Order> orders = orderMapper.queryByMap(map);

		if (null != orders && orders.size() > 0) {
			for (Order order : orders) {
				OrderVo vo = new OrderVo();
				vo.setOrder(order);

				
				if (order.getOrderType() == 2) {
					
					List<ShoppingCartVo> shoppingCartVos = shoppingCartMapper.queryDetailsBySecOrderId(order.getOrderId());
					
					if (null != shoppingCartVos && shoppingCartVos.size() > 0) {
						vo.setShoppingCartVos(shoppingCartVos);
					}
					
				}else {
					
					List<ShoppingCartVo> shoppingCartVos = shoppingCartMapper.queryDetailsByOrderId(order.getOrderId());

					if (null != shoppingCartVos && shoppingCartVos.size() > 0) {
						vo.setShoppingCartVos(shoppingCartVos);
					}
					
				}

				vos.add(vo);
			}
		}
		return vos;
	}

	@Override
	public List<OrderVo> queryRefundOrderList(Map<String, Object> map) {
		List<OrderVo> vos = new ArrayList<OrderVo>();
		List<Order> orders = orderMapper.queryRefundByMap(map);

		if (null != orders && orders.size() > 0) {
			for (Order order : orders) {
				
				OrderVo vo = new OrderVo();
				vo.setOrder(order);

				if (order.getOrderType() == 2) {
					
					List<ShoppingCartVo> shoppingCartVos = shoppingCartMapper.queryDetailsBySecOrderId(order.getOrderId());
					
					if (null != shoppingCartVos && shoppingCartVos.size() > 0) {
						vo.setShoppingCartVos(shoppingCartVos);
					}
					
				}else {
					
					List<ShoppingCartVo> shoppingCartVos = shoppingCartMapper.queryDetailsByOrderId(order.getOrderId());

					if (null != shoppingCartVos && shoppingCartVos.size() > 0) {
						vo.setShoppingCartVos(shoppingCartVos);
					}
					
				}
				vos.add(vo);
			}
		}
		return vos;
	}

	@Override
	public int queryCountByOrderId(String orderId) {
		return orderMapper.queryCountByOrderId(orderId);
	}
	
}
